package com.hundun.vision.biz.robot;

import com.hundun.vision.biz.dto.KlineBarDTO;
import com.hundun.vision.biz.dto.PositionDTO;
import com.hundun.vision.biz.enums.OrderSide;
import com.hundun.vision.biz.request.KlineRequest;
import com.hundun.vision.biz.service.AccountService;
import com.hundun.vision.biz.service.MarketService;
import com.hundun.vision.biz.utils.KlineUtils;
import com.hundun.vision.biz.utils.TimeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.ta4j.core.BarSeries;
import org.ta4j.core.BaseTradingRecord;
import org.ta4j.core.Trade.TradeType;
import org.ta4j.core.TradingRecord;
import org.ta4j.core.num.DecimalNum;

import java.math.BigDecimal;
import java.util.List;

import static com.hundun.vision.biz.enums.OrderSide.BUY;
import static com.hundun.vision.biz.enums.OrderSide.SELL;
import static com.hundun.vision.biz.enums.OrderType.LIMIT;
import static com.hundun.vision.biz.enums.OrderType.MARKET;
import static com.hundun.vision.biz.enums.OrderValidityType.GTC;
import static com.hundun.vision.biz.enums.OrderWorkingType.MARK_PRICE;

/**
 * @author ：RuoChen
 * @date ：10:10 2024/11/30
 * @description：基础机器人
 */
@Service
@Slf4j
public class Robot {
    public static final String BASE_COIN = "USDT";

    @Value("${robot.buySymbol}")
    public String buySymbol;

    @Value("${robot.sellSymbol}")
    public String sellSymbol;

    @Value("${robot.interval}")
    public String interval;

    @Value("${robot.limit}")
    public Integer limit;

    @Value("${robot.leverage}")
    public Integer leverage;
    @Value("${robot.balanceWeight}")
    public BigDecimal balanceWeight;

    @Value("${robot.buyStopLossPercentage}")
    public BigDecimal buyStopLossPercentage;

    @Value("${robot.sellStopLossPercentage}")
    public BigDecimal sellStopLossPercentage;

    @Autowired
    public AccountService accountService;

    @Autowired
    public MarketService marketService;

    public TradingRecord initTradeRecord(PositionDTO position) {
        TradingRecord tradingRecord = null;
        if (position != null) {
            BigDecimal balance = position.getPositionAmt();
            if (balance.compareTo(BigDecimal.ZERO) > 0) {
                tradingRecord = new BaseTradingRecord(TradeType.BUY);
                tradingRecord.enter(0, DecimalNum.valueOf(position.getEntryPrice()), DecimalNum.valueOf(position.getPositionAmt()));
            } else if (balance.compareTo(BigDecimal.ZERO) < 0) {
                tradingRecord = new BaseTradingRecord(TradeType.SELL);
                tradingRecord.enter(0, DecimalNum.valueOf(position.getEntryPrice()), DecimalNum.valueOf(position.getPositionAmt().negate()));
            }
        }
        return tradingRecord;
    }

    /**
     * 获取订单方向
     *
     * @return
     */
    public OrderSide getOrderSide(PositionDTO position) {
        if (position == null) {
            return null;
        }
        OrderSide orderSide = null;
        BigDecimal balance = position.getPositionAmt();
        if (balance.compareTo(BigDecimal.ZERO) < 0) {
            orderSide = SELL;
        } else if (balance.compareTo(BigDecimal.ONE) > 0) {
            orderSide = BUY;
        }
        return orderSide;
    }

    /**
     * 获取K线数据
     *
     * @param symbol
     * @return
     */
    public BarSeries getBarSeries(String symbol) {
        BarSeries barSeries = null;
        try {
            KlineRequest request = new KlineRequest();
            request.setSymbol(symbol);
            request.setInterval(interval);
            request.setLimit(limit);
            request.setStartTime(TimeUtils.getStartTime(interval, limit));
            request.setEndTime(System.currentTimeMillis());
            List<KlineBarDTO> klineBars = marketService.getKlineBar(request);
            barSeries = KlineUtils.buildBarSeries(klineBars, interval);
        } catch (Exception e) {
            log.error("get bar series error", e);
        }
        return barSeries;
    }

    /**
     * 创建订单
     *
     * @param newOrder  建仓订单
     * @param orderSide 交易方向
     * @param price     当前价格
     * @param price     当前价格
     */
    public void createOrder(String symbol, Boolean newOrder, OrderSide orderSide, Boolean loss, BigDecimal price, BigDecimal amount) {
        log.info("robot create order,newOrder:{}|orderSide:{}|loss:{}|price:{}|amount:{}", newOrder, orderSide.getDescription(), loss, price, amount);
        if (newOrder) {
            accountService.createOrder(symbol, orderSide, LIMIT, GTC, MARK_PRICE, price, amount);
        } else {
            accountService.createOrder(symbol, orderSide, MARKET, GTC, MARK_PRICE, price, amount);
        }
    }
}